package utils

import (
	"bytes"
	"errors"
	"io"
	"net/http"
	"net/url"
	"strconv"

	"github.com/xuri/excelize/v2"
)

func OutToFile(w http.ResponseWriter, fileName string, data string) error {
	w.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(fileName))
	w.Header().Set("Content-Description", "File Transfer")
	w.Header().Set("Content-Type", "application/octet-stream")
	w.Header().Set("Content-Transfer-Encoding", "binary")
	w.Header().Set("Expires", "0")
	w.Header().Set("Cache-Control", "must-revalidate")
	w.Header().Set("Pragma", "public")
	io.WriteString(w, data)
	return nil
}

func OutToCsv(w http.ResponseWriter, fileName string, head []string, data [][]string) error {
	content, err := formatCsvData(head, data)
	if err != nil {
		return errors.New("exporting head is null")
	}
	w.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(fileName))
	w.Header().Set("Content-Description", "File Transfer")
	w.Header().Set("Content-Type", "application/octet-stream")
	w.Header().Set("Content-Transfer-Encoding", "binary")
	w.Header().Set("Expires", "0")
	w.Header().Set("Cache-Control", "must-revalidate")
	w.Header().Set("Pragma", "public")
	io.WriteString(w, content)
	return nil
}

func formatCsvData(head []string, data [][]string) (string, error) {
	if len(head) == 0 {
		return "", errors.New("exporting head is null")
	}
	cLen := len(head)
	dataStr := bytes.NewBufferString("\xEF\xBB\xBF") // 写入UTF-8 BOM
	//添加头
	for index, headElem := range head {
		separate := ","
		if index == cLen-1 {
			separate = "\n"
		}
		dataStr.WriteString(headElem + separate)
	}
	//添加数据行
	for _, dataArray := range data {
		if len(dataArray) != cLen { //数据项数小于列数
			return "", errors.New("cloumn of exporting data is error")
		}
		for index, dataElem := range dataArray {
			separate := ","
			if index == cLen-1 {
				separate = "\n"
			}
			dataStr.WriteString(dataElem + separate)
		}
	}
	return dataStr.String(), nil
}

// SheetData 定义工作表数据结构
/*数据格式
{
	Name:    "玩家统计",
	Headers: []string{"区服", "玩家id", "玩家购买时活动天数"},
	Rows: [][]string{
		{"1", "1111", "5天"},
		{"2", "2222", "6天"},
	},
}
*/
type SheetData struct {
	Name    string     // 工作表名称
	Headers []string   // 表头
	Rows    [][]string // 数据行
}

func OutToExcel(w http.ResponseWriter, fileName string, sheets []SheetData) error {
	f := excelize.NewFile()
	defer f.Close()

	// 删除默认工作表（可选）
	f.DeleteSheet("Sheet1")

	// 创建工作表
	for i, sheet := range sheets {
		sheetName := sheet.Name
		if sheetName == "" {
			sheetName = "Sheet" + strconv.Itoa(i+1)
		}

		var sheetID int
		if i == 0 {
			f.SetSheetName("Sheet1", sheetName)
			sheetID = f.GetSheetIndex(sheetName)
		} else {
			sheetID = f.NewSheet(sheetName)
		}
		f.SetActiveSheet(sheetID)
		currentSheet := f.GetSheetName(sheetID)

		for colIdx, header := range sheet.Headers {
			cell, _ := excelize.CoordinatesToCellName(colIdx+1, 1)
			f.SetCellValue(currentSheet, cell, header)
		}

		for rowIdx, row := range sheet.Rows {
			for colIdx, value := range row {
				cell, _ := excelize.CoordinatesToCellName(colIdx+1, rowIdx+2)
				f.SetCellValue(currentSheet, cell, value)
			}
		}
	}

	w.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(fileName))
	w.Header().Set("Content-Description", "File Transfer")
	w.Header().Set("Content-Type", "application/octet-stream")
	w.Header().Set("Content-Transfer-Encoding", "binary")
	w.Header().Set("Expires", "0")
	w.Header().Set("Cache-Control", "must-revalidate")
	w.Header().Set("Pragma", "public")
	// 写入文件流
	return f.Write(w)
}
